/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pa165.bookingmanager.services.impl;

import cz.muni.fi.pa165.bookingmanager.dao.CustomerManager;
import cz.muni.fi.pa165.bookingmanager.dao.HotelManager;
import cz.muni.fi.pa165.bookingmanager.dao.ReservationManager;
import cz.muni.fi.pa165.bookingmanager.entities.Customer;
import cz.muni.fi.pa165.bookingmanager.entities.Hotel;
import cz.muni.fi.pa165.bookingmanager.entities.Reservation;
import cz.muni.fi.pa165.bookingmanager.exceptions.IllegalOrphanException;
import cz.muni.fi.pa165.bookingmanager.exceptions.NonexistentEntityException;
import cz.muni.fi.pa165.bookingmanager.exceptions.PreexistingEntityException;
import cz.muni.fi.pa165.bookingmanager.interceptors.LoggingInterceptor;
import cz.muni.fi.pa165.bookingmanager.interceptors.ShiroSecuredInterceptor;
import cz.muni.fi.pa165.bookingmanager.services.CustomerService;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.interceptor.Interceptors;
import org.apache.shiro.authz.annotation.RequiresRoles;

/**
 *
 * @author Radek Koubsky
 */
@Stateless
@Local(value = CustomerService.class)
public class CustomerServiceImpl implements CustomerService {

    @Resource
    private SessionContext ctx;
    @EJB
    private CustomerManager cusManager;
    
    @EJB
    private HotelManager hotelManager;
     
    @EJB
    private ReservationManager reservationManager;

    @Override
    @Interceptors({ShiroSecuredInterceptor.class, LoggingInterceptor.class})
    @RequiresRoles("receptionist")
    public void createCustomer(Customer customer) throws IllegalOrphanException, PreexistingEntityException {
        if (!isValidEntity(customer)) {
            throw new IllegalArgumentException("Invalid customer entity.");
        }

        try {
            cusManager.createCustomer(customer);
        } catch (Exception ex) {
            ctx.setRollbackOnly();
        }
    }

    @Override
    @Interceptors({ShiroSecuredInterceptor.class, LoggingInterceptor.class})
    @RequiresRoles("receptionist")
    public void updateCustomer(Customer customer) throws NonexistentEntityException, IllegalOrphanException, PreexistingEntityException, Exception {
        if (!isValidEntity(customer)) {
            throw new IllegalArgumentException("Invalid customer entity.");
        }

        try {
            cusManager.updateCustomer(customer);
        } catch (Exception ex) {
            Logger.getLogger(CustomerServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            ctx.setRollbackOnly();
        }
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    @Interceptors({ShiroSecuredInterceptor.class, LoggingInterceptor.class})
    @RequiresRoles("receptionist")
    public void deleteCustomer(Customer customer) throws NonexistentEntityException, IllegalOrphanException {
        try {
            List<Hotel> hotels = hotelManager.findAllHotels();
            for (Hotel h : hotels) {
            List<Reservation> reservations = reservationManager.findAllHotelReservations(h.getId());
            for (Reservation r : reservations) {
                if (r.getCustomers().contains(customer));
                reservationManager.deleteReservation(r);
                
            }
        }
            cusManager.deleteCustomer(customer);
        } catch (Exception ex) {
            Logger.getLogger(CustomerServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            ctx.setRollbackOnly();
        }
    }

    @Override
    @Interceptors(LoggingInterceptor.class)
    public Customer getCustomerById(Long customerId) {
        return cusManager.getCustomerById(customerId);
    }

    @Override
    @Interceptors(LoggingInterceptor.class)
    public List<Customer> findCustomersByName(String customer) {
        List<Customer> customers = cusManager.findCustomersByName(customer);
        return customers;
    }

    @Override
    @Interceptors(LoggingInterceptor.class)
    public List<Customer> findAllCustomers() {
        List<Customer> customers = cusManager.findAllCustomers();
        return customers;
    }

    private boolean isValidEntity(Customer customer) {
        if (customer == null) {
            return false;
        }
        if (customer.getFirstName() == null) {
            return false;
        }

        if (customer.getSurName() == null) {
            return false;
        }

        if (customer.getNumberOfIdCard() == null) {
            return false;
        }

        return true;
    }

    public void setCustomerManager(CustomerManager cusManager) {
        this.cusManager = cusManager;
    }

    public void setHotelManager(HotelManager hotelManager) {
        this.hotelManager = hotelManager;
    }

    public void setReservationManager(ReservationManager reservationManager) {
        this.reservationManager = reservationManager;
    }
}
